use crate::global::DpmError;
use async_trait::async_trait;
use rcmd_core::log::{error, info};
use rcmd_core::util;
use std::env;
use std::fmt::Formatter;
use std::fmt::{self};
use std::fs;
use std::path::Path;

pub const HOOK_DIR: &str = ".dpm_hook";

#[derive(Debug)]
pub enum HookSupport {
    ///
    /// 运行dpm install $pkg 之前的回调
    /// 参数:
    /// $1 current_dir
    /// $2 install_dir
    /// $3 $pkg名称
    BeforeInstall = 0,
    ///
    /// 运行dpm install $pkg 之前的回调
    /// 参数:
    /// $1 current_dir
    /// $2 $pkg名称
    AfterInstall,
}

impl fmt::Display for HookSupport {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            HookSupport::BeforeInstall => write!(f, "before_install"),
            HookSupport::AfterInstall => write!(f, "after_install"),
        }
    }
}

#[async_trait]
pub trait BaseCmd {
    ///如果用到了全局配置， 先加载setting
    fn load_setting() {}

    ///执行hook,hook类似git的hook机制，在构建关键节点执行本地脚本
    fn execute_hook(&self, hook: HookSupport, args: &Vec<String>) {
        let exe = env::current_dir().unwrap();
        let pwd = exe.as_path();
        let h_name = format!("{}{}", hook, if cfg!(windows) { ".bat" } else { "" });
        let h_path = Path::join(pwd, HOOK_DIR)
            .join(&h_name)
            .display()
            .to_string();
        info!("Check execute hook:{}", h_path.as_str());
        let mf = fs::metadata(&h_path);
        if mf.is_ok() {
            info!("found the hook file {}", h_path.as_str());
            for entry in std::fs::read_dir(pwd).unwrap() {
                if let Ok(e) = entry {
                    info!("walk dir {:?}", e.file_name().to_str());
                }
            }

            let (iss, ret) = util::shcmd::run_sh(&h_path, args);
            if iss {
                info!("{}", ret);
            } else {
                error!("{}", ret);
            }
            return;
        }
        info!("No hook {}", h_path.as_str());
    }

    async fn run(&self) -> Result<(), DpmError>;
}
